
/**
 * ----------------------------什么是sass
 * 
 * Sass是成熟、稳定、强大的css预处理器，而SCSS是Sass3版本当中引入的新语法特性，
 * 完全兼容CSS3的同时，也继承了Sass强大的动态功能
 */

/**
 * ---------------------------Scss和Sass区别
 * 
 * 文件扩展名不同：Sass 是以“.sass”后缀为扩展名，而 Scss 是以“.scss”后缀为扩展名
 * 语法书写方式不同：Sass 是以严格的缩进式语法规则来书写，不带大括号({})和分号，而 Scss 用大括号{}取代了原来的缩进。
 * 
 */

/**
 * ---------------------------scss支持的7种数据类型
 * 
 * 数字、字符串、颜色、布尔、空值nul、数组(用空格或逗号做分隔符)、maps(相当于JavaScript的object)
 * 
 * 数字，1rem、2vh、13、 10px；
 * 
 * 字符串，分有引号字符串与无引号字符串，"foo"、 'bar'、baz；
 * 
 * 颜色，blue, #04a3f9, rgba(255,0,0,0.5)；
 * 
 * 布尔型，true和false；
 * 
 * 空值，null是其类型的唯一值。表示缺少值，通常由函数返回以表示缺少结果；、
 * 
 * 数组 (list)，用空格或逗号作分隔符，1.5em 1em 0 2em,Helvetica,Arial,sans-serif；
 * 
 * maps， 相当于 JavaScript的 object，(key1: value1, key2: value2)；
 * 
 */

// 单行注释不会编译到css文件
// 1.变量声明
// Sass变量必须以$开头，变量名和值之间使用冒号隔开

// 全局变量
$mainColor : #092873;
$siteWidth : 1024px;
$borderStyle : dotted;
$content: "First content";
// 如果$content之前没定义就使用如下的默认值
$content: "Second content" !default;

body {
  color: $mainColor;
  background-color: $mainColor;
  // border: 1px $borderStyle $mainColor;
  max-width: $siteWidth;
  height: 100%;
  $min-height:50px;
  $max-height:300px !global;  // 局部变量转全局变量
  
  content: $content;
}

// 2.继承
// Sass模块继承可以通过@extend语法实现

.message {
  border: 1px solid #ccc;
  padding: 10px;
  color: #333;
}
.success {
  @extend .message;
  border-color: green;
}

/**
 * 3.选择器嵌套----父选择器&符号----&符号用于选择器拼接
 * css中重复写选择器很麻烦、scss的选择器嵌套可以避免重复输入父选择器
 */

.container {
    width: 200px;
	height: 200px;
    margin: 0 auto;
	background-color: #ccc;
    .header {
        .img {
			background-color: #333;
            width: 100px;
            height: 60px;
			transition: all 0.5s;
			&:hover{
				background-color: aqua;
			}
        }
		&_title{
			font-size: 18px;
			color: $mainColor;
		}
    }
}

/**
 * 4.圆括号()
 * 可以用来影响运算的顺序，和数学中的效果是一致的。
 * 
 */

/**
 * 5.等值运算符
 * 相等运算== 和不相等运算!=。所有数据类型均支持 == 和!=，另外，每种数据类型也有其各自支持的运算方式。
 * 
 */
// $theme:"blue";
// .container {
//     @if $theme == "blue" {
//         background-color: red;
//     }
//     @else {
//         background-color: blue;
//     }
// }

// .container {
//     @if $theme != "blue" {
//         background-color: red;
//     }@else {
//         background-color: blue;
//     }
// }


/**
 * 6.关系运算符
 * 四个关系运算符< > >= <=
 * 
 */
$theme:3;
.container {
    @if $theme >= 5 {
        background-color: red;
    }
    @else {
        background-color: blue;
    }
}

/**
 * 7.布尔运算符
 * 三个布尔运算符and or not
 * 
 */
$width: 100;
$height: 200;
$last: false;
div {
  @if $width>50 and $height<300 {
    font-size: 16px;
  } @else {
    font-size: 14px;
  }
  @if not $last {
    border-color: red;
  } @else {
    border-color: blue;
  }

  @if $width>500 or $height<300{
    line-height: 20px;
  } @else {
    line-height: 50px;
  }
}

/**
 * 8.数字运算符
 * 五个布尔运算符+ - * / %
 * 
 */
// 纯数字与百分号或单位运算时会自动转化成相应的百分比与单位值 
.container {
	// ================== + 运算===================== 
    width: 50 + 20;
    width: 50 + 20%;
	width: 50% + 20%;
    width: 10pt + 20px;
    width: 10pt + 20;

//     ================== - 运算===================== 
    height: 50 - 20;
    height: 10 - 20%;
    height: 50pt - 20px;

//     ================== * 运算===================== 
    height: 50 * 30;
    height: 10 * 30%;
    height: 50 * 2px;
    height: 50pt * 4;

//     ==================/ 运算 (除完后最多只能保留一种单位)===================== 
	$min-width: 100px;
    width: 10/5;
    width: 10px / 5px;
    width: 10px / 20;
    width: ($min-width / 2); // 使用变量与括号
    height: (500px/2); // 使用了括号

//     ==================% 求余运算===================== 
    width: 10 % 3;
    width: 50px % 7;
    width: 50% % 7;
}

/**
 * 9.字符串运算
 * +可用于连接字符串；
 * 如果有引号字符串（位于 + 左侧）连接无引号字符串，运算结果是有引号的；
 * 无引号字符串（位于 + 左侧）连接有引号字符串，运算结果则没有引号。
 * 
 */
.container {
    content: "Foo " + Bar;
    font-family: sans- + "serif";
}

/**
 * 10.插值语句
 * 通过 # {} 插值语句可以在选择器、属性名、注释中使用变量，使用# {}插值语句将变量包裹起来即可，
 * 和js中的模板字符串很像。
 * 
 */
	$font-size: 12px;
	$line-height: 30px;
	$class-name: danger;
	$attr: color;
	$author: "福大命大";

	p {
	    font: #{$font-size}/#{$line-height} Arial Helvetica, sans-serif;
	}

	/* 
	* 这是文件的说明部分
	* @author: #{$author}
	*/

	a.#{$class-name} {
	    border-#{$attr}: #f00;
	}

/**
 * 11.流程控制
 * sass中流程控制包含四类，也是我们在js中常见的@if、@for、@each、@while
 * @if
 * @if语法和js类似，基本格式是@if...@else if...@else。
 * 
 */
$theme:3;
.container {
	@if $theme >= 5 {
        background-color: red;
	}@else {
		background-color: blue;
	}
}
// ---========================案例=====================================
@mixin triangle($direction:top, $size:30px, $border-color:black) {
  width: 0px;
  height: 0px;
  display: inline-block;
  border-width: $size;
  border-#{$direction}-width: 0;
  @if ($direction==top) {
     border-color: transparent transparent $border-color transparent;
     border-style: dashed dashed solid dashed;
  }
  @else if($direction==right) {
     border-color: transparent transparent transparent $border-color;
     border-style: dashed dashed dashed solid;
  }
  @else if($direction==bottom) {
     border-color: $border-color transparent transparent transparent;
     border-style: solid dashed dashed dashed;
  }
  @else if($direction==left) {
     border-color: transparent $border-color transparent transparent;
     border-style: dashed solid dashed dashed;
  }
}
.p0 {
     @include triangle($size:50px);
}

.p1 {
     @include triangle(right, 50px, red);
}

.p2 {
    @include triangle(bottom, 50px, blue);
}

.p3 {
     @include triangle(left, 50px, green);
}

/**
 * 12=====for在条件范围内重复操作，这个指令包含两种格式：
 * @for $var from <start> through <end>；
 * @for $var from <start> to <end>。
 * 两者区别在于 through 与 to的含义：
 * 使用 through时，条件范围包含 <start> 与 <end>的值；
 * 使用 to时条件范围只包含<start>的值不包含<end>的值；
 * $var 可以是任何变量，比如$i，<start> 和 <end> 必须是整数值。
 */
@for $i from 1 to 3 {
  #loading span:nth-child(#{$i}) {
      width: 20 * ($i - 1) + px;
  }
}

// 如果把to换成through  查看执行效果



/**
 * 13=====@each
 * @each指令的格式是@each $var in $list , $var可以是任何变量名，
 * 比如$length 或者$name，而$list是一连串的值，也就是值列表。
 */
$color-list:red green blue turquoise darkmagenta;
@each $color in $color-list {
    $index: index($color-list, $color);
    .p#{$index - 1} {
        background-color: $color;
    }
}


/**
 * 14=====@while
 * @while 指令循环输出直到表达式返回结果为 false。这样可以实现比@for 更复杂的循环。
 * 比如，可以借此生成栅格化布局。
 */

$column:12;
@while $column>0 {
   .col-sm-#{$column} {
      width: $column / 12 * 100%;
   }
    $column:$column - 1;
}



/**
 * 15=====@import  支持多文件导入，用“,”号隔开
 * @import算是一个比较简易的模块系统。
 * scss拓展了@import 的功能，允许其导入 scss或 sass文件。
 * 被导入的文件将合并编译到同一个 css文件中，
 * 被导入的文件中所包含的变量或者混合指令 (mixin) 都可以在导入的文件中使用。
 */

// common.scss
$color:red;
// index.scss
// @import "common.scss";
.container {
    border-color: $color;
}
/**
 * 以下情况下，@import 仅作为普通的css语句，不会导入scss文件：
 * 文件名以 http://开头；
 * 文件名是url()；
 * @import包含媒体查询。
 */
// @import "common.css";
// @import url(common);
// @import "http://xxx.com/xxx";
// @import 'landscape' screen and (orientation:landscape);

/**
 * 导入文件也可以使用 # {} 插值语句（下面有讲，这里把它理解成js中模板字符串就行）动态导入，
 * 但不是通过变量动态导入 scss文件，只能作用于 css的 url()导入方式
 */
// $family: unquote("Droid+Sans");
// @import url("http://fonts.googleapis.com/css?family=#{$family}");

/**
 * 16.@Partials（只会在koala环境生效）
 * 如果需要导入 scss或者 sass文件，但又不希望将其编译为 css，
 * 只需要在文件名前添加下划线，这样会告诉 scss不要编译这些文件。
 * 注意：
 * 		导入语句中不需要添加下划线；
 * 		不可以同时存在添加下划线与未添加下划线的同名文件，添加下划线的文件将会被忽略。
 * 
 * Partials主要是用来定义公共样式的，专门用于被其他的 scss文件 import进行使用的。
 */



/**
 * 17.================@media 媒体查询增强
 * scss中，@media 指令与 css中用法一样，只是增加了一点额外的功能，允许在css规则中嵌套。
 * 如果@media 嵌套在 css规则内，编译时，@media 将被编译到文件的最外层，包含嵌套的父选择器。
 * 这个让 @media 方便不少，不需要重复写选择器，也不会打乱 css的书写流程。
 */
.sidebar {
  width: 300px;
  // 横屏（orientation: landscape），竖屏（orientation:portrait）
  @media screen and (orientation: landscape) {
    width: 500px;
    .item {
      height: auto;
    }
  }
}

/**
 * 18.================@mixin 混入
 * 混合指令（Mixin）用于定义可重复使用的样式。
 * 混合指令可以包含所有的css规则，绝大部分 scss规则，
 * 甚至可以通过参数功能引入变量，输出多样化的样式。
 * @mixin mixin-name() { css 声明 }
 * 使用
 * @include mixin-name;
 */
// 定义一个区块基本的样式
@mixin block {
    width: 96%;
    margin-left: 2%;
    border-radius: 8px;
    border: 1px #f6f6f6 solid;
}
// 使用混入 
.container {
    .block {
        @include block;
    }
}

// 18.1=====单参数
// 定义flex布局元素纵轴的排列方式
@mixin flex-align($aitem) {
    align-items: $aitem;
}

// 只有一个参数，直接传递参数
.container {
    @include flex-align(center);
}

// 18.2=====多参数
// 定义块元素内边距
@mixin block-padding($top, $right, $bottom, $left) {
    padding-top: $top;
    padding-right: $right;
    padding-bottom: $bottom;
    padding-left: $left;
}

// 按照参数顺序赋值
.container1 {
   @include block-padding(10px, 20px, 30px, 40px);
}

// 可指定参数赋值
.container2 {
   @include block-padding($left: 20px, $top: 10px, $bottom: 10px, $right: 30px);
}

// 可指定参数赋值，但是必须指定4个值，不能缺失
.container3 {
   @include block-padding($left: 10px, $top: 10px, $bottom: 0, $right: 0);
}

// 18.3==========指定默认值
// 定义块元素内边距，参数指定默认值
@mixin block-padding($top:0, $right:0, $bottom:0, $left:0) {
    padding-top: $top;
    padding-right: $right;
    padding-bottom: $bottom;
    padding-left: $left;
}

// 可指定参数赋值
.container {
    /** 不带参数 */
    @include block-padding;
    /** 按顺序指定参数值 */
    @include block-padding(10px,20px);
    /** 给指定参数指定值 */
    @include block-padding($left: 10px, $top: 20px)
}

// 18.4=========可变参数
// 使用...处理参数不固定的情况，类似于js中的函数的剩余参数
@mixin linear-gradient($direction, $gradients...) {
    background-color: nth($gradients, 1);
    background-image: linear-gradient($direction, $gradients);
}

.table-data {
    @include linear-gradient(to right, #F00, orange, yellow);
}

/**
 * 18.5======总结
 * mixin是可以重复使用的一组css声明，有助于减少重复代码，只需声明一次，就可在文件中引用；
 * 混合指令可以包含所有的 css规则，绝大部分scss规则，可以传递参数，输出多样化的样式；
 * 使用参数时建议加上默认值；
 * @import导入局部模块化样式（类似功能、同一组件）；
 * @minix定义的是可重复使用的样式
 */


/**
 * 19.@function
 * @function用于封装复杂的操作，可以很容易地以一种可读的方式抽象出通用公式和行为，
 * 函数提供返回值，常用来做计算方面的工作。
 */
@function square($base) {
    @return $base * $base * 1px;
}

.sidebar {
    float: left;
    margin-left: square(4);
}

/**
 * 19.1=========可变参数
 * 参数列表还可用于采用任意关键字参数
 * 
 */
@function sum($numbers...) {
    $sum: 0;
    @each $number in $numbers {
        $sum: $sum + $number;
    }
    @return $sum;
}

$widths: 50px, 30px, 100px;
.micro {
    width: sum($widths...);
}

/**
 * 19.2===总结
 * @function和@mixin参数的使用方式没啥区别；
 * @function用来计算，@mixin用来封装样式，@import用来抽离他们为一个模块。
 */



/**
 * 20.==========@use
 * 存在兼容性问题，仅在Dart Sass 1.23.0以上有效，官方文档有兼容性介绍。
 * 
 * scss真正意义上的模块化，可以从其它 scss样式表中加载mixin、function和变量，
 * 并将来自多个样式表的 css组合在一起。
 * 
 * scss还提供了很多内置模块，我们可以通过@use使用。
 */

// @use "src/corners" as c;
// .button {
//     @include c.rounded;
//     padding: 5px + c.$radius;
// }


/**
 * 21.====@at-root、
 * @at-root用来跳出嵌套，在多级嵌套时比较常用，包含without和with。
 */
.demo {
    animation: motion 3s infinite;
    @at-root {
        @keyframes motion {
        }
    }
}


/**
 * 21.======sass中的内置函数（扩展）
 * scss内置扩展分为color list map math meta selector string等，
 * 扩展也就是scss内置的一些function，每个模块下内容比较多，这里用一些常用的进行举例。
 */


/**
 * 21.1====color
 * scss包含很多操作颜色的函数。例如lighten()与 darken()可用于调亮或调暗颜色，
 * opacify()使颜色透明度减少，transparent()使颜色透明度增加，mix()用来混合两种颜色。
 */
.p1 {
    // 让颜色变亮
    color:scale-color(#5c7a29, $lightness: +30%);
}

.p2 {
    // 让颜色变暗
    color:scale-color(#5c7a29, $lightness: -15%);
}

.p3 {
    // 降低颜色透明度
    color:scale-color(#5c7a29, $alpha: -40%);
}


/**
 * 21.2====string
 * scss有许多处理字符串的函数，比如向字符串添加引号的quote()、unquote()去掉引号
 * string-length()。
 */
p {
    &:after {
		// 给字符串加引号
        content: quote(这是里面的内容);
    }
    background-color: unquote($string: "#F00");
    z-index:str-length("scss学习");
	
}


/**
 * 21.3====Math函数
 * 数值函数处理数值计算，例如：percentage()将无单位的数值转换为百分比，
 * round()将数字四舍五入为最接近的整数，min()和max()获取几个数字中的最小值或最大值，
 * random()返回一个随机数。
 */
p {
    z-index: abs(-15); // 15
    z-index: ceil(5.8); //6
	z-index: floor(5.8); // 5
    z-index: max(5, 1, 6, 8, 3); //8
    z-index: min(5, 1, 6, 8, 3); //8
    opacity: random(); // 随机 0-1
}


/**
 * 21.4====List
 * List函数操作List，length()返回列表长度，
 * nth()返回列表中的特定项，join()将两个列表连接在一起，
 * append()在列表末尾添加一个值。
 */
p {
    z-index: length(12px); //1
    z-index: length(12px 5px 8px); //3
    z-index: index(a b c d, c); //3
    padding: append(10px 20px, 30px); // 10px 20px 30px
    color: nth($list: red blue green, $n: 2); // blue
	width: join(1 2 3,4 5 6);
}


/**
 * 21.4====Map
 * Map函数操作Map，map-get()根据键值获取map中的对应值，
 * map-merge()来将两个map合并成一个新的map，map-values()映射中的所有值。
 * map-has-key(map,key)判断map中是否有某个键
 */
$font-sizes: ("small": 12px, "normal": 18px, "large": 24px);
$padding:(top:10px, right:20px, bottom:10px, left:30px);
p {
    font-size: map-get($font-sizes, "normal"); //18px
    @if map-has-key($padding, "right") {
        padding-right: map-get($padding, "right");
    }
    &:after {
        content: map-keys($font-sizes) + " "+ map-values($padding) + "";
    }
}